// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IteratorPopulator.cs" company="Jakob Christensen">
//   Copyright (C) by Jakob Christensen
// </copyright>
// <summary>
//   Defines the <see cref="IteratorPopulator" /> class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace AgentJohnson.Generators
{
  using System.Collections.Generic;
  using Resharper.Abstractions.CodeDom.Statements.DeclarationStatements;
  using Resharper.Abstractions.Generators;
  using Resharper.Abstractions.Shell;

  /// <summary>
  /// Defines the <see cref="IteratorPopulator"/> class.
  /// </summary>
  public class IteratorPopulator : IGeneratorPopulator
  {
    #region Public Methods

    /// <summary>
    /// Populates the specified data context.
    /// </summary>
    /// <param name="context">
    /// The data context.
    /// </param>
    /// <returns>
    /// Returns the I enumerable.
    /// </returns>
    public IEnumerable<GeneratorBase> Populate(DataContext context)
    {
      var model = this.GetModel(context);
      if (model == null)
      {
        yield break;
      }

      yield return new IteratorGenerator(model, string.Format("foreach (var item in {0})", model.VariableName), "foreach (var $item$ in " + model.VariableName + ")\r\n{$END$\r\n}\r\n", "item", "suggestVariableName()");
    }

    #endregion

    #region Methods

    /// <summary>
    /// Gets the model.
    /// </summary>
    /// <param name="context">
    /// The context.
    /// </param>
    /// <returns>
    /// Returns the model.
    /// </returns>
    private Model GetModel(DataContext context)
    {
      var treeNode = context.TreeNode;
      if (treeNode == null)
      {
        return null;
      }

      var statement = context.GetPreviousStatement() as DeclarationStatement;
      if (statement == null)
      {
        return null;
      }

      foreach (var variableDeclaration in statement.VariableDeclarations)
      {
        if (!variableDeclaration.Type.IsEnumerable)
        {
          continue;
        }

        if (variableDeclaration.Type.ToString() == "string")
        {
          continue;
        }

        var typeName = variableDeclaration.Type.ToString();

        return new Model
        {
          VariableName = variableDeclaration.Name, 
          TypeName = typeName
        };
      }

      return null;
    }

    #endregion

    /// <summary>
    /// Defines the <see cref="Model"/> class.
    /// </summary>
    public class Model
    {
      #region Public Properties

      /// <summary>
      ///   Gets or sets the name of the type.
      /// </summary>
      /// <value>The name of the type.</value>
      public string TypeName { get; set; }

      /// <summary>
      ///   Gets or sets the name of the variable.
      /// </summary>
      /// <value>The name of the variable.</value>
      public string VariableName { get; set; }

      #endregion
    }
  }
}